package ltd.jdsoft.cute.perm.interceptor;

import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import ltd.jdsoft.cute.common.session.SecuritySession;
import ltd.jdsoft.cute.perm.helper.PermHelper;
import ltd.jdsoft.cute.perm.model.Menu;
import ltd.jdsoft.cute.perm.model.Role;
import ltd.jdsoft.cute.perm.model.User;
import ltd.jdsoft.cute.perm.service.MenuService;
import ltd.jdsoft.cute.perm.service.RoleService;
import ltd.jdsoft.cute.spring.web.exception.NoRightOperationException;
import ltd.jdsoft.cute.spring.web.exception.UnAuthorizedException;

/**
 * 权限身份证拦截器
 * 
 * @author zhengzhq
 *
 */
@Component
public class SessionPermInterceptor implements HandlerInterceptor {

  private static Logger logger = LoggerFactory.getLogger(SessionPermInterceptor.class);
  private static AntPathMatcher pathMatcher = new AntPathMatcher();

  private static final String mainPageUrl = "/admin/main";
  private static final String welcomePageUrl = "/admin/welcome";
  private static final List<String> excludeUris =
      Arrays.asList("/admin", "/admin/login", "/admin/logout");
  @Autowired
  private PermHelper permHelper;
  @Autowired
  private RoleService roleService;
  @Autowired
  private MenuService menuService;

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    User user = permHelper.getUserFromRequest(request);
    if (user != null) {
      SecuritySession.set(user);
    }

    // 首先获取请求的uri
    String uri = request.getRequestURI().toString();
    // 去掉contextPath
    if (uri.startsWith(request.getContextPath())) {
      uri = uri.replaceFirst(request.getContextPath(), "");
    }
    boolean isExcludeUri = excludeUris.contains(uri);

    // 如果当前请求不需要校验菜单权限，那么直接返回，不继续鉴权
    if (isExcludeUri) {
      return true;
    }

    // 需要检验
    if (user == null) {
      throw new UnAuthorizedException();
    }

    // 如果当前访问的是主页，用户登录过后直接放行
    if (mainPageUrl.equals(uri) || welcomePageUrl.equals(uri)) {
      return true;
    }

    // 进入以下逻辑的部分代表需要判断菜单权限
    Role role = roleService.get(user.getRoleId());
    // 获取角色下的菜单
    List<Menu> menuList = menuService.getMenuList(role.getMenuIds());
    for (Menu menu : menuList) {
      if (!StringUtils.isEmpty(menu.getUrlPattern())
          && pathMatcher.match(menu.getUrlPattern(), uri)) {
        return true;
      }
    }

    logger.warn("url: {} will be break.", uri);

    // 无权操作
    throw new NoRightOperationException();
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {

  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
      Object handler, Exception ex) throws Exception {
    // 请求结束的时候本地线程清空保存的用户信息
    SecuritySession.clearOnOver();
  }
}
